package com.cyanite.playlv2;

import com.cyanite.playlv2.app.LoadableListActivityWithViewAndHeader;
import com.cyanite.playlv2.util.MenuUtils;
import com.cyanite.playlv2.util.UiUtil;
import com.cyanite.playlv2.widget.HotSubTripListAdapter;
import com.cyanite.playlv2.widget.FocusSubTripListAdapter;
import com.cyanite.playlv2.widget.SegmentedButton;
import com.cyanite.playlv2.widget.SegmentedButton.OnClickListenerSegmentedButton;
import com.cyanite.playlv2api.types.Task;
import com.cyanite.playlv2api.types.Trip;
import com.cyanite.playlv2api.types.Group;
import com.cyanite.playlv2.R;

import android.app.Activity;
import android.app.AlertDialog;
import android.app.Dialog;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.DialogInterface;
import android.content.Intent;
import android.content.IntentFilter;
import android.content.DialogInterface.OnCancelListener;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.os.AsyncTask;
import android.os.Bundle;
import android.view.KeyEvent;
import android.view.LayoutInflater;
import android.view.Menu;
import android.view.MenuItem;
import android.view.View;
import android.view.View.OnClickListener;
import android.view.ViewGroup;
import android.widget.AdapterView;
import android.widget.Button;
import android.widget.ImageView;
import android.widget.LinearLayout;
import android.widget.ListView;
import android.widget.ScrollView;
import android.widget.Toast;

public class TripActivity extends LoadableListActivityWithViewAndHeader {

    private static final int ACTIVITY_TRIP_DETAIL = 815;
    private static final int MENU_GROUP_SEARCH = 0;
    private static final int MENU_REFRESH = 1;
    private static final int MENU_SEARCH = 2;
    private static final int MENU_CREATE_TRIP = 3;
    private static final int DIALOG_PICK_CATEGORY = 1;
    private static final int DIALOG_ERROR = 2;

    private StateHolder mStateHolder;
    private ViewGroup mLayoutEmpty;
    private FocusSubTripListAdapter mFocusSubTripListAdapter;
    private HotSubTripListAdapter mHotSubTripListAdapter;

    private BroadcastReceiver mLoggedOutReceiver = new BroadcastReceiver() {
        @Override
        public void onReceive(Context context, Intent intent) {
            finish();
        }
    };

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        registerReceiver(mLoggedOutReceiver, new IntentFilter(PlayLv2.INTENT_ACTION_LOGGED_OUT));

    	mStateHolder = new StateHolder();
        ensureUi();

        PlayLv2 playlv2 = (PlayLv2)getApplication();
        if (playlv2.isReady()) {
            mStateHolder.startTaskGetTasks(this);
        }
    }

    @Override
    public void onResume() {
        super.onResume();
    }

    @Override
    public void onPause() {
        super.onPause();

        if (isFinishing()) {
            unregisterReceiver(mLoggedOutReceiver);
            mStateHolder.cancel();
        }
    }

    @Override
    public boolean onCreateOptionsMenu(Menu menu) {
        super.onCreateOptionsMenu(menu);
        menu.add(MENU_GROUP_SEARCH, MENU_REFRESH, Menu.NONE, R.string.refresh)
                .setIcon(R.drawable.ic_menu_refresh);
        menu.add(MENU_GROUP_SEARCH, MENU_SEARCH, Menu.NONE, R.string.search_label)
                .setIcon(R.drawable.ic_menu_search);
        menu.add(Menu.NONE, MENU_CREATE_TRIP, Menu.NONE, R.string.preferences_trip_add_title)
                .setIcon(R.drawable.ic_menu_create_trip);
        MenuUtils.addPreferencesToMenu(this, menu);
        return true;
    }

    @Override
    public boolean onOptionsItemSelected(MenuItem item) {
        switch (item.getItemId()) {
            case MENU_REFRESH:
                refreshTripsAndTasks();
                return true;
            case MENU_SEARCH:
                showDialog(DIALOG_PICK_CATEGORY);
                return true;
            case MENU_CREATE_TRIP:
                startActivity(new Intent(TripActivity.this, TripCreateMainActivity.class));
                return true;
            default:
                break;
        }
        return super.onOptionsItemSelected(item);
    }

    @Override
    protected void onActivityResult(int requestCode, int resultCode, Intent data) {
        if (requestCode == ACTIVITY_TRIP_DETAIL) {
            if (resultCode == Activity.RESULT_OK) {
            }
        }
    }

    @Override
    public int getNoSearchResultsStringId() {
        return R.string.no_trip_created;
    }

    @Override
    public boolean onKeyDown(int keyCode, KeyEvent event) {
        if (keyCode == KeyEvent.KEYCODE_BACK) {
            Dialog dialog = new AlertDialog.Builder(this)
            .setTitle(this.getResources().getString(R.string.app_name))
            .setMessage(this.getResources().getString(R.string.exit_note))
            .setPositiveButton(this.getResources().getString(R.string.ok), new DialogInterface.OnClickListener() {
                public void onClick(DialogInterface dialog, int whichButton) {
                    finish();
                    android.os.Process.killProcess(android.os.Process.myPid());
                }
            }).setNegativeButton(this.getResources().getString(R.string.cancel), new DialogInterface.OnClickListener() {
                public void onClick(DialogInterface dialog, int whichButton) {
                }
            }).create();
            dialog.show();
            return true;
        }
        else
            return super.onKeyDown(keyCode, event);
    }

    private void ensureUi() {
        setRefreshProgressBarEnable(false);
        SegmentedButton buttons = getHeaderButton();
        buttons.clearButtons();
        buttons.addButtons(
            getString(R.string.trips_activity_btn_focus),
            getString(R.string.trips_activity_btn_hot));
        buttons.setFocusable(false);

        if (mStateHolder.isTripPage()) {
            buttons.setPushedButtonIndex(1);
        } else  {
            buttons.setPushedButtonIndex(0);
        }

        buttons.setOnClickListener(new OnClickListenerSegmentedButton() {
            @Override
            public void onClick(int index) {
                if (index == 0) {
                    mStateHolder.setIsTripPage(false);
                }
                else if (index == 1) {
                    mStateHolder.setIsTripPage(true);
                    if (!mStateHolder.getIsRunningGetTrips() && !mStateHolder.isRunnedOnceGetTrips() )   {
                        mStateHolder.startTaskGetTrips(TripActivity.this);
                    }
                }
                ensureUiListView();
            }
        });

        ImageView btnRefresh = getRightButton();
        btnRefresh.setBackgroundResource(R.drawable.refresh_button);
        btnRefresh.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                refreshTripsAndTasks();
                getRightButton().setBackgroundResource(R.drawable.refresh_button_normal);
                setRefreshProgressBarEnable(true);
            }
        });

        ImageView btnSearch = getLeftButton();
        btnSearch.setBackgroundResource(R.drawable.search_button);
        btnSearch.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                showDialog(DIALOG_PICK_CATEGORY);
            }
        });
        ensureUiListView();
    }

    private void ensureUiListView() {
        SegmentedButton buttons = getHeaderButton();
        buttons.setVisibility(View.VISIBLE);

        ListView listView = getListView();
        listView.setDividerHeight(0);
        listView.setOnItemClickListener(new ListView.OnItemClickListener() {
            @Override
            public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
                if (mStateHolder.isTripPage()) {
                    Trip trip = (Trip) parent.getAdapter().getItem(position);
                    Intent intent = new Intent(TripActivity.this, TripDetailsActivity.class);
                    intent.putExtra(TripDetailsActivity.EXTRA_TRIP_PARCEL, trip);
                    startActivityForResult(intent, ACTIVITY_TRIP_DETAIL);
                }   else {
                    Task task = (Task) parent.getAdapter().getItem(position);
                    Intent intent = new Intent(TripActivity.this, AddTipsActivity.class);
                    intent.putExtra(AddTipsActivity.EXTRA_TASK_PARCEL, task);
                    startActivity(intent);
                }
            }
        });

        LayoutInflater inflater = LayoutInflater.from(this);
        if (UiUtil.sdkVersion() > 3) {
            mLayoutEmpty = (ScrollView)inflater.inflate(
                    R.layout.trips_activity_empty, null);

            Button btnCreateTrips = (Button)mLayoutEmpty.findViewById(
                    R.id.tripsActivityEmptyBtnAddTrips);
            btnCreateTrips.setOnClickListener(new OnClickListener() {
                @Override
                public void onClick(View v) {
                    Intent intent = new Intent(TripActivity.this, TripCreateMainActivity.class);
                    startActivity(intent);
                }
            });
        } else {
            mLayoutEmpty = (ScrollView)inflater.inflate(
                    R.layout.trips_activity_empty_sdk3, null);
        }
        mLayoutEmpty.setLayoutParams(new LinearLayout.LayoutParams(
                LinearLayout.LayoutParams.FILL_PARENT, LinearLayout.LayoutParams.FILL_PARENT));

        loadTwoKindsListView();
    }

    private void refreshTripsAndTasks() {
        if (!mStateHolder.getIsRunningGetTasks() &&
                !mStateHolder.getIsRunningGetTrips()) {
            if (mStateHolder.isTripPage())  {
                mStateHolder.setTripsPage(1);
                mStateHolder.startTaskGetTrips(this);
                mStateHolder.setIsTripRefreshing(true);
            }   else {
                mStateHolder.setTasksPage(1);
                mStateHolder.startTaskGetTasks(this);
                mStateHolder.setIsTaskRefreshing(true);
            }
        }   else {
            Toast.makeText(TripActivity.this,
                    getResources().getString(R.string.trips_activity_loading),
                    Toast.LENGTH_LONG).show();
        }
    }

    private void loadTwoKindsListView() {
        if ( mStateHolder.isTripPage() )   {
            Group<Trip> trips = mStateHolder.getTrips();
            if (!mStateHolder.isPreviousTripPage() && mHotSubTripListAdapter != null
                    && mHotSubTripListAdapter.getCount() != 0) {
                getListView().setAdapter(mHotSubTripListAdapter);
                mStateHolder.setPreviousIsTripPage(true);
                return;
            }
            mStateHolder.setPreviousIsTripPage(true);

            if ( trips != null && trips.size() > 0 ) {
                //Collections.sort(trips, Comparators.getTripRecencyComparator());
                if ( mStateHolder.getTripsPage() == 1 ){
                    mHotSubTripListAdapter = new HotSubTripListAdapter(this,
                            ((PlayLv2) getApplication()).getRemoteResourceManager(), btnOnClickListenerHot);
                    mHotSubTripListAdapter.setGroup(trips);
                    getListView().setAdapter(mHotSubTripListAdapter);
                }else{
                    mHotSubTripListAdapter.notifyDataSetChanged();
                    mHotSubTripListAdapter.setMoreRefresh(false);
                }
            }   else {
                getListView().setAdapter(null);
                setEmptyView(mLayoutEmpty);
            }
        }   else {
            Group<Task> tasks = mStateHolder.getTasks();
            if (mStateHolder.isPreviousTripPage() && mFocusSubTripListAdapter != null
                    && mFocusSubTripListAdapter.getCount() != 0) {
                getListView().setAdapter(mFocusSubTripListAdapter);
                mStateHolder.setPreviousIsTripPage(false);
                return;
            }
            mStateHolder.setPreviousIsTripPage(false);

            if (tasks != null && tasks.size() > 0 ) {
                 if ( mStateHolder.getTasksPage() == 1 ){
                     mFocusSubTripListAdapter = new FocusSubTripListAdapter(this,
                             ((PlayLv2) getApplication()).getRemoteResourceManager(), btnOnClickListenerFocus, true);
                     mFocusSubTripListAdapter.setGroup(tasks);
                     getListView().setAdapter(mFocusSubTripListAdapter);
                 }else{
                     mFocusSubTripListAdapter.notifyDataSetChanged();
                     mFocusSubTripListAdapter.setMoreRefresh(false);
                 }
            }   else {
                getListView().setAdapter(null);
                setEmptyView(mLayoutEmpty);
            }
        }
        if (mStateHolder.getIsRunningGetTasks() ||
                mStateHolder.getIsRunningGetTrips()) {
            setProgressBarIndeterminateVisibility(true);
            setLoadingView();
        } else {
            setProgressBarIndeterminateVisibility(false);
        }
    }

    private FocusSubTripListAdapter.ButtonRowClickHandler btnOnClickListenerFocus = new FocusSubTripListAdapter.ButtonRowClickHandler(){
        @Override
        public void onImageClick(Task task) {
            Bitmap bitmapOriginal = null;
            if (task.getPhotoBitmap() != null)  {
                bitmapOriginal = task.getPhotoBitmap();
            }   else {
                bitmapOriginal = BitmapFactory.decodeResource(TripActivity.this.getResources(), R.drawable.trip_default_photo);
            }
            if (bitmapOriginal != null) {
                ShowImageDialog dlg = new ShowImageDialog(TripActivity.this, bitmapOriginal,
                                                                        getWindowManager().getDefaultDisplay().getWidth());
                dlg.show();
            }
        }

        @Override
        public void onMoreClick() {
            if (!mStateHolder.getIsRunningGetTasks() &&
                !mStateHolder.getIsRunningGetTrips())   {
                mStateHolder.setTasksPage(mStateHolder.getTasksPage()+1);
                mStateHolder.startTaskGetTasks(TripActivity.this);
            }   else {
                Toast.makeText(TripActivity.this,
                        getResources().getString(R.string.trips_activity_loading),
                        Toast.LENGTH_LONG).show();
            }
        }
    };

    private HotSubTripListAdapter.ButtonRowClickHandler btnOnClickListenerHot = new HotSubTripListAdapter.ButtonRowClickHandler(){

        @Override
        public void onImageClick(Trip trip) {
            Bitmap bitmapOriginal = null;
            if (trip.getPhotoBitmap() != null)  {
                bitmapOriginal = trip.getPhotoBitmap();
            }   else {
                bitmapOriginal = BitmapFactory.decodeResource(TripActivity.this.getResources(), R.drawable.trip_default_photo);
            }
            if (bitmapOriginal != null) {
                ShowImageDialog dlg = new ShowImageDialog(TripActivity.this, bitmapOriginal,
                                                                        getWindowManager().getDefaultDisplay().getWidth());
                dlg.show();
            }
        }

        @Override
        public void onMoreClick() {
            if (!mStateHolder.getIsRunningGetTasks() &&
                    !mStateHolder.getIsRunningGetTrips())  {
                mStateHolder.setTripsPage(mStateHolder.getTripsPage()+1);
                mStateHolder.startTaskGetTrips(TripActivity.this);
            }   else {
                Toast.makeText(TripActivity.this,
                        getResources().getString(R.string.trips_activity_loading),
                        Toast.LENGTH_LONG).show();
            }
        }
    };

    private void onTaskStart() {
        setProgressBarIndeterminateVisibility(true);
        setLoadingView();
    }

    private void onGetTripsTaskComplete(Group<Trip> trips, Exception ex) {

        getRightButton().setBackgroundResource(R.drawable.refresh_button);
        setRefreshProgressBarEnable(false);
    	mStateHolder.setIsRunningGetTrips(false);
    	mStateHolder.setIsRunnedOnceGetTrips(true);
        setProgressBarIndeterminateVisibility(false);

        if ( trips != null && trips.size() > 0 ) {
            mStateHolder.setTrips(trips);
        }
        loadTwoKindsListView();
    }

    private static class TaskGetTrips extends AsyncTask<Void, Void, Group<Trip>> {

    	private PlayLv2 mPlayLv2;
    	private TripActivity mActivity;
        private Exception mException;
        private int mTripsPage;

        public TaskGetTrips(TripActivity activity, int tripsPage) {
            mPlayLv2 = ((PlayLv2) activity.getApplication());
        	mActivity = activity;
        	mTripsPage = tripsPage;
        }

        @Override
        public Group<Trip> doInBackground(Void... params) {
        	try {
        	    return mPlayLv2.getPlayLv2Api().tripsHot(mTripsPage);
            } catch (Exception ex) {
            	mException = ex;
            	return null;
            }
        }

        @Override
        protected void onPreExecute() {
            mActivity.onTaskStart();
        }

        @Override
        public void onPostExecute(Group<Trip> trips) {
        	if (mActivity != null) {
        		mActivity.onGetTripsTaskComplete(trips, mException);
        	}
        }
    }

    private void onGetTasksComplete(Group<Task> tasks, Exception ex) {
       getRightButton().setBackgroundResource(R.drawable.refresh_button);
       setRefreshProgressBarEnable(false);
       mStateHolder.setIsRunningGetTasks(false);
       setProgressBarIndeterminateVisibility(false);

       if ( tasks != null && tasks.size() > 0 ) {
           mStateHolder.setTasks(tasks);
       }
       loadTwoKindsListView();
   }

    private static class TaskGetTasks extends AsyncTask<Void, Void, Group<Task>> {

        private TripActivity mActivity;
        private Exception mException;
        private int mTasksPage;

        public TaskGetTasks(TripActivity activity, int tasksPage) {
            mActivity = activity;
            mTasksPage = tasksPage;
        }

        @Override
        public Group<Task> doInBackground(Void... params) {
            try {
                return ((PlayLv2) mActivity.getApplication()).getPlayLv2Api().tasksFocused(mTasksPage);
            } catch (Exception ex) {
                mException = ex;
                return null;
            }
        }

        @Override
        protected void onPreExecute() {
            mActivity.onTaskStart();
        }

        @Override
        public void onPostExecute(Group<Task> tasks) {
            if (mActivity != null) {
                mActivity.onGetTasksComplete(tasks, mException);
            }
        }
    }

    protected Dialog onCreateDialog(int id) {
        switch (id) {
            case DIALOG_PICK_CATEGORY:
                SearchDialog dlg = new SearchDialog(this);
                dlg.setOnCancelListener(new OnCancelListener() {
                    @Override
                    public void onCancel(DialogInterface dialog) {
                        removeDialog(DIALOG_PICK_CATEGORY);
                    }
                });
                return dlg;

            case DIALOG_ERROR:
                break;
        }
        return null;
    }

    private static class StateHolder {
        private Group<Trip> mTrips;
        private boolean mIsRunningGetTrips;
        private boolean mIsRunningGetTasks;
        private boolean mIsRunnedGetTripsOnce;
        private TaskGetTrips mTaskGetTrips;
        private TaskGetTasks mTaskGetTasks;
        private int mTripsPage;
        private int mTasksPage;
        private Group<Task> mTasks;
        private boolean mIsTripPage;
        private boolean mPreviousIsTripPage;
        private boolean mIsTripRefreshing;
        private boolean mIsTaskRefreshing;

        public StateHolder() {
            mIsRunningGetTrips = false;
        	mIsRunningGetTasks = false;
        	mIsRunnedGetTripsOnce = false;
        	mIsTripPage = false;
        	mPreviousIsTripPage = false;
        	mIsTripRefreshing = false;
        	mIsTaskRefreshing = false;
        	mTripsPage = 1;
        	mTasksPage = 1;
        }

        public boolean isTripPage() {
            return mIsTripPage;
        }

        public void setIsTripPage(boolean isTripPage) {
            mIsTripPage = isTripPage;
        }

        public void setIsTripRefreshing(boolean isRefreshing) {
            mIsTripRefreshing = isRefreshing;
        }

        public void setIsTaskRefreshing(boolean isRefreshing) {
            mIsTaskRefreshing = isRefreshing;
        }

        public boolean isPreviousTripPage() {
            return mPreviousIsTripPage;
        }

        public void setPreviousIsTripPage(boolean isTripPage) {
            mPreviousIsTripPage = isTripPage;
        }

        public boolean isRunnedOnceGetTrips() {
            return mIsRunnedGetTripsOnce;
        }

        public void setIsRunnedOnceGetTrips(boolean isRunned) {
            mIsRunnedGetTripsOnce = isRunned;
        }

        public Group<Trip> getTrips() {
            return mTrips;
        }

        public void setTrips(Group<Trip> trips) {
            if ( mTrips == null || mTrips.size() == 0) {
                mTrips = trips;
            } else if (mIsTripRefreshing )  {
                mTrips.clear();
                mIsTripRefreshing = false;
                mTrips = trips;
            } else {
                mTrips.remove(mTrips.size()-1);
                for(Trip it:trips){
                    mTrips.add(it);
                }
            }
            mTrips.add(new Trip());
        }

        public Group<Task> getTasks() {
            return mTasks;
        }

        public void setTasks(Group<Task> tasks) {
            if ( mTasks == null || mTasks.size() == 0) {
                mTasks = tasks;
            } else if (mIsTaskRefreshing )  {
                mTasks.clear();
                mIsTaskRefreshing = false;
                mTasks = tasks;
            } else{
                mTasks.remove(mTasks.size()-1);
                for(Task it:tasks){
                    mTasks.add(it);
                }
            }
            mTasks.add(new Task());
        }

        public void setTripsPage(int page)   {
            mTripsPage = page;
        }

        public int getTripsPage(){
            return mTripsPage;
        }

        public void setTasksPage(int page)   {
            mTasksPage = page;
        }

        public int getTasksPage(){
            return mTasksPage;
        }

        public boolean getIsRunningGetTrips() {
        	return mIsRunningGetTrips;
        }

        public void setIsRunningGetTrips(boolean isRunning) {
            mIsRunningGetTrips = isRunning;
        }

        public boolean getIsRunningGetTasks() {
            return mIsRunningGetTasks;
        }

        public void setIsRunningGetTasks(boolean isRunning) {
            mIsRunningGetTasks = isRunning;
        }

        public void startTaskGetTrips(TripActivity activity) {
        	if (!mIsRunningGetTrips) {
        	    mTaskGetTrips = new TaskGetTrips(activity, mTripsPage);
        	    mTaskGetTrips.execute();
        	    mIsRunningGetTrips = true;
        	}
        }

        public void startTaskGetTasks(TripActivity activity) {
            if ( !mIsRunningGetTasks ) {
                mTaskGetTasks = new TaskGetTasks(activity, mTasksPage);
                mTaskGetTasks.execute();
                mIsRunningGetTasks = true;
            }
        }

        public void cancel() {
        	if (mIsRunningGetTasks) {
        	    mTaskGetTasks.cancel(true);
        	    mIsRunningGetTasks = false;
        	}
        	if (mIsRunningGetTrips) {
        	    mTaskGetTrips.cancel(true);
                mIsRunningGetTrips = false;
            }
        }
    }
}
